package cn.youfule.mecs.netty;


import cn.youfule.mecs.netty.protocol.*;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class MecsHandler extends SimpleChannelInboundHandler<MecsProtocol> {

    private static List<AbstractHandler> handlers;
    static {
        handlers = new ArrayList<>();
        handlers.add(new LoginHandler());
        handlers.add(new LogoutHandler());
        handlers.add(new QueryHandler());
        handlers.add(new ReportHandler());
        handlers.add(new UpgradeHandler());
        handlers.add(new SettingHandler());
        handlers.add(new HeartbeatHandler());
        handlers.add(new SearchHandler());
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, MecsProtocol prot) throws Exception {
        for (AbstractHandler handler:handlers){
            if(handler.isSupport(prot)){
                handler.channelRead(ctx,prot);
            }
        }
        //交给下一个处理程序
        //ctx.fireChannelRead(prot);
    }

    /**
     * 客户端主动连接服务端
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        InetSocketAddress socket = (InetSocketAddress) ctx.channel().remoteAddress();
        String ip = socket.getAddress().getHostAddress();
        log.info("收到客户端IP: " + ip);

        ChannelSupervise.addChannel(ip,ctx.channel());
        ctx.fireChannelActive();
    }

    /**
     * 客户端主动断开服务端的链接,关闭流
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        InetSocketAddress socket = (InetSocketAddress) ctx.channel().remoteAddress();
        String ip = socket.getAddress().getHostAddress();
        log.info( "通道不活跃，进行关闭："+ip);

        ChannelSupervise.removeChannel(ip);
        // 关闭流
        ctx.close();
    }

    /**
     * 发生异常处理
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx,cause);
        ctx.fireExceptionCaught(cause);
        //ctx.close();
    }
}
